﻿// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// This file is part of CodingEditor.
// Note:	This project is derived from Peter Project
//			(hosted on sourceforge and codeplex)
//
// Copyright (c) 2008-2009, CE Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


namespace CE.Splash
{
	using System;
	using System.Reflection;
	using System.Threading;
	using System.Windows.Forms;

	public static class Splasher
	{
		#region Fields

		private static Form _SplashForm;
		private static ISplashForm _SplashInterface;
		private static Thread _SplashThread;
		private static string _TempStatus = string.Empty;

		#endregion Fields

		#region Delegates

		private delegate void SplashStatusChangedHandle(string NewStatusInfo);

		#endregion Delegates

		#region Properties

		public static string Status
		{
			set{
				if (_SplashInterface == null || _SplashForm == null) {
					_TempStatus = value;
					return;
				}
				_SplashForm.Invoke(
				        new SplashStatusChangedHandle(str => _SplashInterface.SetStatusInfo(str)),
				        new object[] {value}
				        );
			}
		}

		#endregion Properties

		#region Methods

		public static void Close()
		{
			if (_SplashThread == null || _SplashForm == null) return;

			try {
				_SplashForm.Invoke(new MethodInvoker(_SplashForm.Close));
			}
			catch{
			}
			_SplashThread.Abort();
			_SplashThread = null;
			_SplashForm = null;
		}

		public static void Show(Type splashFormType, string callerVersion)
		{
			if (_SplashThread != null)
				return;
			if (splashFormType == null) {
				throw (new Exception("splashFormType is null"));
			}

			_SplashThread = new Thread(delegate()
			                           {
			                                   CreateInstance(splashFormType, callerVersion);
			                                   Application.Run(_SplashForm);
						   }) {
				IsBackground = true
			};

			_SplashThread.SetApartmentState(ApartmentState.STA);
			_SplashThread.Start();
		}

		private static void CreateInstance(Type FormType, string callerVersion)
		{
			object[] args = { callerVersion };
			object obj =
			        FormType.InvokeMember(null, BindingFlags.DeclaredOnly | BindingFlags.Public |
			                              BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.CreateInstance,
			                              null, null, args);

			_SplashForm = obj as Form;
			_SplashInterface = obj as ISplashForm;
			if (_SplashForm == null) {
				throw (new Exception("Splash Screen must inherit from System.Windows.Forms.Form"));
			}
			if (_SplashInterface == null) {
				throw (new Exception("must implement interface ISplashForm"));
			}

			if (!string.IsNullOrEmpty(_TempStatus))
				_SplashInterface.SetStatusInfo(_TempStatus);
		}

		#endregion Methods
	}
}